#ifndef __XOTABLE__
#define __XOTABLE__

namespace xm
{
	class XoTable : public IKXoTable, UnkBase
	{
	protected:
		xv::xvalue_t _Root;
	public:
		UNKNOWN_IMP1(IKXoTable);
		DEFAULT_INIT_CLASS();
	public:
		STDMETHOD(PutXo)( LPCSTR aName, xv::AnyValue & v )
		{
			if( !aName ) return E_INVALIDARG;
			if( !_Root.set( aName, v ) ) return E_FAIL;
			return S_OK;
		}
		STDMETHOD(GetXo)( LPCSTR aName, xv::AnyValue & v )
		{
			if( !aName ) return E_INVALIDARG;
			if( !_Root.get( aName, (xv::xvalue_t&)v ) )
				return E_FAIL;
			return S_OK;
		}
		STDMETHOD(DelXo)( LPCSTR aName )
		{
			if( !aName ) return E_INVALIDARG;
			if( !_Root.erase( aName ) )
				return E_FAIL;
			return S_OK;
		}
		STDMETHOD(Clear)()
		{
			_Root.clear();
			return S_OK;
		}
		STDMETHOD(SetUnknown)( LPCSTR aName, IUnknown * po )
		{
			xv::xvalue_t v( po );
			return PutXo( aName, v );
		}
		STDMETHOD(GetUnknown)( LPCSTR aName, REFIID riid, IUnknown ** pp )
		{
			xv::xvalue_t v;
			RFAILED( GetXo( aName, v ) );
			RASSERT( v.isUnknownPtr(), E_FAIL );
			if( !v.punk ) return E_FAIL;
			return v.punk->QueryInterface( riid, (void**)pp );
		}

	};

	class Arguments : public IKArguments, UnkBase
	{
	protected:
		xv::xvalue_t	mRoot;
	public:
		Arguments()
		{
		}

		UNKNOWN_IMP1(IKArguments);

		HRESULT init_class( IUnknown * , IUnknown * ) 
		{
			return mRoot.asObject() ? S_OK : E_OUTOFMEMORY;
		}

		STDMETHOD(Clear)()
		{
			refp<xv::vObject> obj = mRoot.asObject();
			if( !obj ) return E_OUTOFMEMORY;
			return obj->clear() ? S_OK : E_FAIL;
		}

		STDMETHOD(SetArgv)( LPCSTR path, xv::AnyValue& val )
		{
			xv::xvalue_t current = mRoot;
			char key[xv::MAX_KEY_LEN+1];
			for( ; *path; ++ path )
			{
				LPCSTR next = tcschr( path, '/' );
				if( !next )
				{
					return current.set( path, val ) ? S_OK : E_FAIL;
				}
				else
				{
					size_t len = next-path;
					if( !len ) continue;

					memcpy( key, path, len );

					path += len;
					key[len] = 0; 

					if( !current.get( key, current ) )
					{
						xv::xvalue_t tmp; 
						if( !tmp.changeType(xv::dObject) )
							return E_FAIL;

						if( !current.set( key, tmp ) )
							return E_FAIL;

						current = tmp;
					}
				}
			}
			return E_FAIL;
		}
		STDMETHOD(GetArgv)( LPCSTR path, xv::AnyValue& val )
		{
			xv::xvalue_t current = mRoot;
			CHAR key[xv::MAX_KEY_LEN+1];
			for( ; *path; ++ path )
			{
				LPCSTR next = tcschr( path, '/' );
				if( !next )
				{
					return current.get( path, val ) ? S_OK : E_FAIL;
				}
				else
				{
					size_t len = next-path;
					if( !len ) continue;
					memcpy( key, path, len ); key[len] = 0; 
					path += len;
					if( !current.get( key, current ) )
						return E_FAIL;
				}
			}
			return E_FAIL;
		}

		STDMETHOD(SetArgvByString)( LPCSTR aParamString )
		{
			if( !aParamString ) return E_FAIL;
			LPCSTR eq = tcschr( aParamString, '=' );
			if( !eq )
			{
				if( aParamString[0] == '!' )
				{
					xv::xvalue_t swtich(0);
					return SetArgv( aParamString+1, (xv::AnyValue&)swtich );
				}
				else
				{
					xv::xvalue_t swtich(1);
					return SetArgv( aParamString, (xv::AnyValue&)swtich );
				}
			}
			else
			{
				size_t len = eq - aParamString;
				if( len > xv::MAX_KEY_LEN ) return E_FAIL;
				CHAR key[xv::MAX_KEY_LEN+1];
				memcpy( key, aParamString, len );
				key[len] = 0;
				++ eq;
				xv::xvalue_t val;
				bool fok = false;
				if( *eq == ':' )
				{
					fok = val.set( eq + 1 );
				}
				else if( isalpha(*eq) )
				{
					fok = val.set( eq );
				}
				else if( *eq == '#' ) 
				{
					int v = 0;
					if( !sscanf( eq + 1, "%X", &v ) )
						return E_FAIL;
					fok = val.set( v );
				}
				else
				{
					int v = 0;
					if( !sscanf( eq, "%d", &v ) )
						return E_FAIL;
					fok = val.set( v );
				}

				if( !fok ) return E_FAIL;

				return SetArgv( key, val );
			}
		}
	};





};



#endif